<?php

/*------------------------------------------------
*
*   Explay Engine Content Management System.
*   Copyright © 2008 Golovdinov Alexander.
*
*-------------------------------------------------
*
*   Official site: wwww.alex-home.spb.ru/explay.html
*   Contact e-mail: golovdinov@gmail.com
*
*   GNU General Public License original source:
*   http://www.gnu.org/licenses/gpl-3.0.html
*
------------------------------------------------*/


if (!defined ('EXPLAY')) exit;

class Templater {
	
	public static $path = '';
	public static $user = '';
	public static $user_id = 0;
	public static $author_id = 0;
	private static $error = '';
	private static $auto_put_errors = true;
	private static $auto_clear_vars = true;
	private static $vars = array ();
	private static $static_vars = array ();
	private static $static_out = array ();
	private static $count_ = 0;
	private static $cache = array ();
	
	private static $templates_parts = array (); // массив с кусками шаблона
	
	private static $map = array ();
	private static $user_mapper = true;
	private static $current_template = '';
	
	/**
	 * Установка переменной
	 *
	 * @param string $varname имя переменной в шаблоне
	 * @param mixed $var переменная
	 */
	public static function set_var ($varname, $var) {
		self::$vars[$varname] = $var;
	}
	
	/**
	 * Установка статичных переменных, действующих во всех шаблонах
	 *
	 * @param string $start_var имя переменной в шаблоне
	 * @param mixed $out_var переменная
	 */
	public static function set_static_var ($start_var, $out_var) {
		array_push (self::$static_vars, $start_var);
		array_push (self::$static_out, $out_var);
	}
	
	/**
	 * Очиска переменных, имя которых передано через запятую
	 */
	public static function unset_vars () {
		$num_vars = func_num_args ();
		$vars = func_get_args ();
		
		for ($i=0; $i<$num_args; ++$i) {
			if (isset (self::$vars[$vars[$i]]))
				unset (self::$vars[$vars[$i]]);
			else
				throw new Exception ('Undefined variable '.self::$vars[$vars[$i]]);
		}
	}
	
	/**
	 * Возвращает обработанный шаблон
	 *
	 * @param string $file путь к файлу относительно папки с шаблонами
	 * @param boolean $auto_clear необязательный параметр, по-умолчанию установленный в true, указывающий на необходимость очистки переменных
	 * @return string
	 */
	public static function display ($file, $auto_clear = true) {
		if (!self::is_cached($file)) self::cache_file ($file);
		
		$file = self::$cache[$file];
		
		return self::render ($file, $auto_clear);
	}
	
	/**
	 * Обработка шаблона
	 *
	 * @param string $file путь к файлу относительно папки с шаблонами
	 * @param boolean $auto_clear необязательный параметр, по-умолчанию установленный в true, указывающий на необходимость очистки переменных
	 * @return string
	 */
	private static function render ($file, $auto_clear = true) {
		
		// Ищем переменные вида {$var}
		preg_match_all ("#{\\$(.+?)}#", $file, $template_vars);
		$cntvars = count ($template_vars[0]);
		
		// Заменяем переменные
		for ($i=0; $i<$cntvars; ++$i) {
			$tvar = $template_vars[1][$i];
			$parts = explode ('->', $tvar); // разбиваем на переменную и ключ массива
			$tvarname = trim ($parts[0]);
			if (!isset(self::$vars[$tvarname])) {
				$file = str_replace ('{$'.$tvar.'}', 'undefined variable', $file); // Переменная не была определена или определена несуществующая переменная
			}
			elseif (!empty($parts[1])) { // В переменной шаблона есть ключ массива
				$key = trim ($parts[1]);
				$file = str_replace ('{$'.$tvar.'}', self::$vars[$tvarname][$key], $file);
			} else { // нет ключа
				$file = str_replace ('{$'.$tvar.'}', self::$vars[$tvarname], $file);
			}
		}
		
		// Заменяем статичные переменные
		$cntvars = count(self::$static_vars);
		for ($i=0; $i < $cntvars; ++$i) {
			$file = str_replace (self::$static_vars[$i], self::$static_out[$i], $file);
		}
				
		if (self::$user == 'admin') {
			$file = preg_replace ("#<unregister>(.+?)</unregister>#is", '', $file);
			$file = preg_replace ("#<register>(.+?)</register>#is", "\\1", $file);
			$file = preg_replace ("#<admin>(.+?)</admin>#is", "\\1", $file);
			$file = preg_replace ("#<moderator>(.+?)</moderator>#is", "\\1", $file);
		}
		elseif (self::$user == 'moderator') {
			$file = preg_replace ("#<unregister>(.+?)</unregister>#is", '', $file);
			$file = preg_replace ("#<admin>(.+?)</admin>#is", '', $file);
			$file = preg_replace ("#<register>(.+?)</register>#is", "\\1", $file);
			$file = preg_replace ("#<moderator>(.+?)</moderator>#is", "\\1", $file);
		}
		elseif (self::$user == 'register') {
			$file = preg_replace ("#<unregister>(.+?)</unregister>#is", '', $file);
			$file = preg_replace ("#<admin>(.+?)</admin>#is", '', $file);
			$file = preg_replace ("#<register>(.+?)</register>#is", "\\1", $file);
			$file = preg_replace ("#<moderator>(.+?)</moderator>#is", '', $file);
		}
		else {
			$file = preg_replace ("#<unregister>(.+?)</unregister>#is", "\\1", $file);
			$file = preg_replace ("#<admin>(.+?)</admin>#is", '', $file);
			$file = preg_replace ("#<register>(.+?)</register>#is", '', $file);
			$file = preg_replace ("#<moderator>(.+?)</moderator>#is", '', $file);
		}
		
		if (self::$user_id == self::$author_id || self::$user == 'admin' || self::$user == 'moderator') {
			$file = preg_replace ("#<author>(.+?)</author>#is", "\\1", $file);
		} else {
			$file = preg_replace ("#<author>(.+?)</author>#is", '', $file);
		}
				
		preg_match_all ("#<include=(.+?)>#is", $file, $include);
		for ($i=0; $i<count($include[0]); $i++) {
			$file = str_replace ("<include={$include[1][$i]}>", self::get_file($include[1][$i]), $file);
		}
			
		// Очищаем текущие переменыые
		if ($auto_clear) self::clear_vars();
		
		if (self::$auto_put_errors && self::$error != '') self::errors();
		
		return $file;
	}
	
	/**
	 * Загружает группу шаблонов
	 *
	 * Автоматически разбивает загруженный шаблон на части
	 * согласно синтаксису 0_о
	 * Давать этому методу обычный шаблон смысла нет
	 *
	 * @param string $file путь к файлу относительно папки с шаблонами
	 * @param boolean $auto_clear необязательный параметр, по-умолчанию установленный в true, указывающий на необходимость очистки загруженных частей
	 * @return string
	 */
	public static function load ($file, $clear_loaded = true) {
		if (!self::is_cached($file)) self::cache_file ($file);
		$file = self::$cache[$file];
		
		if ($clear_loaded) self::$templates_parts = array ();
				
		preg_match_all ("#<!--part:(.+?)-->(.+?)<!--/part:\\1-->#is", $file, $templates_parts);
		
		$cnt = count ($templates_parts[0]);
		$dump = array ();
		
		for ($i=0; $i<$cnt; ++$i) {
			$key = $templates_parts[1][$i];
			self::$templates_parts[$key] = $templates_parts[2][$i];
		}
		
		unset ($dump);
		
		//print_r (self::$templates_parts);
	}
	
	/**
	 * Возвращает обработанную часть группогого шаблона
	 *
	 * @param string $key имя части группогого шаблона
	 * @param boolean $auto_clear необязательный параметр, по-умолчанию установленный в true, указывающий на необходимость очистки переменных
	 * @return string
	 */
	public static function display_part ($key, $auto_clear = true) {
		if (!isset (self::$templates_parts[$key])) return false;
		return self::render (self::$templates_parts[$key], $auto_clear);
	}
	
	/**
	 * Граббит файл
	 */
	private static function get_file ($file) {
		$file = $_SERVER['DOCUMENT_ROOT'].'/'.$file;
		
		$file = str_replace ("'", '', $file);
		$file = str_replace ('"', '', $file);
		
		if (!file_exists($file)) {
			self::$error .= "&#8212; Файл не существует: <strong>$file</strong>!<br />\n";
			return "<br /><strong>Template error:</strong> Файл не существует: <strong>$file</strong>!<br />\n";
		}
		elseif (file_exists($file)) {
			
			if ($geting_file = file_get_contents($file)) {
				return $geting_file;
			}
			else if (self::$path == "") {
				self::$error .= "&#8212; Ошибка подгрузки файла: <strong>$file</strong>!<br />\n";
				return "<br /><strong>Template error:</strong> Ошибка подгрузки файла: <strong>$file</strong>!<br />\n";
			}
			
		}
	}
	
	/**
	 * Выполняет очистку переменных
	 */
	public static function clear_vars () {
		self::$vars = array ();
		self::$author_id = 0;
	}
	
	/**
	 * Выводит ошибки компиляции шаблонов
	 */
	private static function errors () {
		if (self::$path == '') self::$error .= '&#8212; Не указан путь к папке с шаблонами!<br />';
		if (self::$user == '') self::$error .= '&#8212; Не указана группа пользователя!<br />';
		if (self::$error != '') {
			print '<div style="border: #FF0000 1px dashed; background-color: #FFDDDD; color: #BB0000; padding: 3px">'.
				'<strong>Template errors:</strong><p>'.self::$error.
				'</div>';
		}
	}
	
	/**
	 * Возвращает кол-во загруженных шаблонов (не использованных)
	 *
	 * @return integer
	 */
	public static function past_count () {
		return (int) self::$count_;
	}
	
	/**
	 * Проверяет, кеширован шаблон или нет
	 */
	private static function is_cached ($name)  {
		if (isset(self::$cache[$name])) return true;
		else return false;
	}
	
	/**
	 * Кеширует файл шаблона
	 */
	private static function cache_file ($file) {
		
		if (file_exists(self::$path.$file)) {
			$content = file_get_contents (self::$path.$file);
			
			self::$cache[$file] = $content;
		}
		else self::$error .= "&#8212; Файл шаблона не существует: <strong>$file</strong>!<br />\n";
		
		if (self::$auto_put_errors && self::$error != '') self::errors();
		
		self::$count_++;
		
		return;
	}

}

